#include "businessFunc.h"
#include <stdbool.h>
#include "stdShared.h"
#include <json-c/json.h>
#include "doubleLinkList.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include "commonTool.h"
#include "stdDataBase.h"


/* 外部声明 */
extern DoubleLinkList * g_list;

/* 静态函数前置声明 */
static int chatRoomServerNoticeInfo(UserInfo * info);
static const char * packageJsonStr(FUNCTION_OPTION businessType, REGIS_CODE responseCode);


/* 解析业务选项 */
enum FUNCTION_OPTION parseBusinessOption(const char * str, enum FUNCTION_OPTION *choice)
{
    if (str == NULL)
    {
        return NULL_PTR;
    }

    /* 将json字符串转成json对象 */
    struct json_object * obj = json_tokener_parse(str);
    /* 检查是否解析失败 */
    if (obj == NULL)
    {
        return NULL_PTR;
    }
    
    if (choice)
    {
        *choice = (FUNCTION_OPTION)json_object_get_int(json_object_object_get(obj, "type"));    
    }

    return ON_SUCCESS;
}

/* 服务器封装返回状态信息给客户端：业务类型的枚举值，响应状态码的枚举值 */
static const char * packageJsonStr(FUNCTION_OPTION businessType, REGIS_CODE responseCode)
{
    /* step1: 创建json对象 */
    struct json_object * object = json_object_new_object();
    if (object == NULL)
    {
        perror("json_object_new_object error");
        exit(-1);
    }

    /* 在json对象中添加<key, value> */
    json_object_object_add(object, "type", json_object_new_int(businessType));
    json_object_object_add(object, "status_code", json_object_new_int(responseCode));
    
    
    /* 将json对象转化成字符串 */
    const char * str = json_object_to_json_string(object);
    if (str == NULL)
    {
        perror("json to string error");//转换失败
        return NULL;
    }

    return str;
}

/* 用于处理注册业务 */
/* str是json类型的字符串 : {"type" : REGIS, "username" : "zhangsan", "passwd" : "XXXXXX"} */
/* connfd：表示与客户端的连接套接字描述符。 */
int chatRoomServerRegister(int connfd, const UserInfo * info)
{
    /* 注册:定义一个 responseCode 变量，用于表示注册结果的状态码，初始值为注册成功。 */
    enum REGIS_CODE responseCode = REGIS_SUCCESS;
    const char * responseJsonStr = NULL; 
    /* step1: 用户名, 密码合法性校验 */
    if (checkUserNameLegal(info->username) != true || checkPasswdLegal(info->passwd) != true)
    {
        printf("用户名或者密码不合法\n");
        /* 表示生成注册无效的JSON字符串 */
        responseJsonStr = packageJsonStr(REGIS, REGIS_INVAILD);
        if (responseJsonStr == NULL)
        {
            perror("packageJsonStr error");
            return NULL_PTR;
        }
        else
        {
            /* 发送给客户端 */
            write(connfd, responseJsonStr, strlen(responseJsonStr));
        }
    }

    /* step2: 判断该用户是否已经注册 */
    if (userInfoIsRegistered(&info))
    {
        printf("该用户已经被注册了");
        responseJsonStr = packageJsonStr(REGIS, REGIS_REPEAT);
        if (responseJsonStr == NULL)
        {
            perror("packageJsonStr error");
            return NULL_PTR;
        }
        else
        {
            /* 发送给客户端 */
            write(connfd, responseJsonStr, strlen(responseJsonStr));
        }
    }

    /* 该用户没有被注册 */
    /* 存储到数据库 - 用户表 */
    saveUserInfo(&info);
    
    /* 生成表示注册结果的 */
    responseJsonStr = packageJsonStr(REGIS, responseCode);
    if (responseJsonStr == NULL)
    {
        perror("packageJsonStr error");
        return NULL_PTR;
    }
    else
    {
        /* 发送数据(注册状态码) 到客户端 */
        write(connfd, responseJsonStr, strlen(responseJsonStr));
    }

    return 0;
}


/* 服务器通知该用户所有【在线】好友: 该用户上线 */
static int chatRoomServerNoticeInfo(UserInfo * info)
{

    /* 取当前用户的所有【在线】好友对应的上线信息 */
    // 需要知道对应在线好友的fd信息, 可以维护一数组(将磁盘数据映射到内存), 做循环发送。
#if 0
    
    int * onlineFriendNums = (int *)malloc(sizeof() * int);
    if (onlineFriendNums == NULL)
    {

    }

    /* 循环发送 上线信息 */
    for (int idx = 0; idx < ; idx++)
    {
        write(onlineFriendNums[idx], )
    }
#endif

    return ON_SUCCESS;
}

/* 登陆业务 */
/* 
    connfd：表示与客户端的连接套接字描述符。
    info：  表示用户信息的指针，包括用户名和密码。
*/
int chatRoomServerLogIn(int connfd, const UserInfo * info)
{
    if (info == NULL)
    {
        return NULL_PTR;
    }
    /* 声明了用于存储注册响应状态码和响应 JSON 字符串的变量 */
    enum LOGIN_CODE responseCode = LOGIN_SUCCESS;

    const char * responseJsonStr = NULL;
    /* step1: 用户名, 密码合法性校验 */
    if (checkUserNameLegal(info->username) != true || checkPasswdLegal(info->passwd) != true)
    {
        printf("用户名或者密码不合法\n");
        responseCode = LOGIN_INVAILD;   
        responseJsonStr = packageJsonStr(LOGIN, responseCode);
        if (responseJsonStr == NULL)
        {
            perror("packageJsonStr error");
        }
        else
        {
            /* 返回登录无效状态码给客户端。 */
            write(connfd, (void *)responseJsonStr, strlen(responseJsonStr));
        }
    }

    /* step2: 判断该用户是否已经注册 */
    if (!userInfoIsRegistered(info))
    {
        printf("该用户未注册");
        responseCode = LOGIN_NO_REGISTER;
        responseJsonStr = packageJsonStr(LOGIN, responseCode);
        if (responseJsonStr == NULL)
        {
            perror("packageJsonStr error");
        }
        else
        {
            write(connfd, (void *)responseJsonStr, strlen(responseJsonStr));
        }
    }

    /* 校验用户名和密码 是否正确 */
    if (checkUserUserPasswd(info))
    {
        
    }
    int loginStatus = checkUserUserPasswd(info);

    /* 发送数据(登陆状态码) 到客户端 */
    /* todo... */
    // write()


    /* 维护在线列表 */
    /* 
        检测链表中是否存在该用户 
            1.  如果该用户已经登陆 - 处理手段: 已经登陆, 不允许重新登陆
            2.  如果该用户没在登陆 - 可以登陆
    */
    /* 每次用户上线需要插入到链表中 */

    UserToConnfd mapInfo;
    /* 清空脏数据 */
    memset(&mapInfo, 0, sizeof(mapInfo));

    /* 1. 用户名 */
    strcpy(mapInfo.username, info->username);
    /* 2. 同户名对应的通信句柄 */
    mapInfo.connfd = connfd;

#if 0
    /* 内存数据库 */
    bool existFlag = DoubleLinkListIsExistAppointData(g_list, (void *)&mapInfo, compareUserNameFunc);
    if (existFlag == true)
    {
        
        /* 已经登陆了 */
        write(connfd, LOGIN_REPEAT, sizeof(int));
    }
#else
    /* IO磁盘数据库 */

#endif

    responseJsonStr = packageJsonStr(LOGIN, responseCode);
    if (responseJsonStr == NULL)
    {
        perror("packageJsonStr error");
    }
    else
    {
        /* 发送登录成功的状态码 */
        write(connfd, (void *)responseJsonStr, strlen(responseJsonStr));
    }

    /* 登陆成功之后, 服务器通知该用户所有的好友, 该用户上线 */
    chatRoomServerNoticeInfo(info);

#if 0
    /* 将用户信息维护到 在线链表中 */
    DoubleLinkListTailInsert(g_list, info->username);
#else
    /* 磁盘IO数据库 */
    /* 将用户上线的信息维护到 数据库中 */

#endif

    return ON_SUCCESS;
}


/* 添加好友 */
int chatRoomServerAddFriend(int connfd, const UserInfo * info)
{
    /* */
    
}

/* 删除好友 */
int chatRoomServerDelFriend(int connfd, const UserInfo * info)
{

}



/* 聊天 - 私聊 */
int chatRoomServerPriChat(int connfd, const MessageInfo *info)
{
    if (info->flag == PRI_CHAT)
    {
        /* 私聊 */
        /* info->dstUser是好友名 */

        /* todo... */
        /* usename <-> fd 映射 */
        /* 1.在线列表中(数据库)取 */
        /* 2.在线列表中(内存中)取 */
        
    }
    else
    {
        
    }
    return ON_SUCCESS;
}

/* 聊天 - 群聊 */
int chatRoomServerSharedChat(int connfd, const MessageInfo *info)
{
    if (info->flag == GROUP_CHAT)
    {
        /* 群聊 */
        /* info->dstUser是群名称 */
        /* */

    }
    else
    {

    }
    return ON_SUCCESS;
}

/* 心跳检测 */
int chatRoomServerHeartBeat(UserInfo *info)
{
    return 0;
}